﻿namespace AB.ServiceDirectory.Dao
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Commons.DataFilters;
    using Entities;

    /// <summary>
    /// Class AnhContactDao
    /// </summary>
    public sealed class AContactDao
    {
        /// <summary>
        /// Data Context
        /// </summary>
        private readonly ServicesDirectoryDataContext _dataContext = DB.Context;

        /// <summary>
        /// Finds all contacts.
        /// </summary>
        /// <returns></returns>
        public ICollection<Contact> FindAllContacts()
        {
            var list = from contact in _dataContext.Contacts
                       select contact;

            return list.ToList();
        }

        /// <summary>
        /// Finds the contact by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Contact FindContactById(int id)
        {
            var contact = _dataContext.Contacts.FirstOrDefault(c => c.ContactId == id);
            return contact;
        }

        /// <summary>
        /// Checks the email existed.
        /// </summary>
        /// <param name="email">The email.</param>
        /// <returns></returns>
        public bool CheckEmailExisted(string email)
        {
            var contact = _dataContext.Contacts.FirstOrDefault(c => c.Email == email);
            if (contact != null)
                return true;
            return false;
        }

        /// <summary>
        /// Adds the contact.
        /// </summary>
        /// <param name="contact">The contact.</param>
        /// <returns></returns>
        public bool AddContact(Contact contact)
        {
            try
            {
                _dataContext.Contacts.InsertOnSubmit(contact);
                _dataContext.SubmitChanges();
                return true;
            }
            catch (NullReferenceException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
        }

        /// <summary>
        /// Searches the contact.
        /// </summary>
        /// <param name="firstName">The first name.</param>
        /// <param name="surname">Name of the sur.</param>
        /// <returns>Context list</returns>
        public ICollection<Contact> SearchContact(string firstName, string surname)
        {
            var queryContact = from c in _dataContext.Contacts select c;
            if (!string.IsNullOrEmpty(firstName))
            {
                queryContact = queryContact.Where(c => c.FirstName.StartsWith(firstName));
            }
            if (!string.IsNullOrEmpty(surname))
            {
                queryContact = queryContact.Where(c => c.Surname.StartsWith(surname));
            }
            return queryContact.ToList();
        }

        /// <summary>
        /// Edits the contact.
        /// </summary>
        /// <param name="editedContact">The edited contact.</param>
        /// <returns>true/false result</returns>
        public bool EditContact(Contact editedContact)
        {
            var contactType = _dataContext.ContactTypes.FirstOrDefault(ct => ct.ContactTypeId == editedContact.ContactTypeId);
            try
            {
                var contact = _dataContext.Contacts.FirstOrDefault(c => c.ContactId == editedContact.ContactId);
                if (contact != null)
                {
                    contact.FirstName = editedContact.FirstName;
                    contact.Surname = editedContact.Surname;
                    contact.KnownAs = editedContact.KnownAs;
                    contact.BestContactMethodId = editedContact.BestContactMethodId;
                    contact.OfficePhone = editedContact.OfficePhone;
                    contact.JobRole = editedContact.JobRole;
                    contact.WorkBase = editedContact.WorkBase;
                    contact.HomePhone = editedContact.HomePhone;
                    contact.JobTitle = editedContact.JobTitle;
                    contact.Email = editedContact.Email;
                    contact.IsActive = editedContact.IsActive;
                    contact.ContactType = contactType;
                    contact.MobilePhone = editedContact.MobilePhone;
                    contact.Email = editedContact.Email;
                    contact.IsActive = editedContact.IsActive;

                    _dataContext.SubmitChanges();
                    return true;
                }

                return false;
            }
            catch (NullReferenceException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
        }

        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <param name="startRowIndex">Start index of the row.</param>
        /// <param name="max">The max.</param>
        /// <returns>Contact list query</returns>
        public IQueryable<Contact> GetList(AContactFilter filter, string sortType, int startRowIndex, int max)
        {
            var data = from c in _dataContext.Contacts
                       select c;

            // 1. Filter by condition
            if (filter != null)
            {
                data = GetListQuery(data, filter);
            }

            // 2. Sorting
            data = GetListSort(data, sortType);

            // 3. Limit the rows
            data = data.Skip(startRowIndex).Take(max);

            return data;
        }

        /// <summary>
        /// Gets the list sort.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <returns></returns>
        private static IQueryable<Contact> GetListSort(IQueryable<Contact> data, string sortType)
        {
            var sortDescending = false;

            if (!string.IsNullOrEmpty(sortType))
            {
                var values = sortType.Split(' ');
                sortType = values[0];

                if (values.Length > 1)
                {
                    sortDescending = (values[1] == "DESC");
                }

                switch (sortType)
                {
                    case "ContactName":
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.FirstName).ThenBy(c => c.Surname)
                                   : data.OrderBy(c => c.FirstName).ThenBy(c => c.Surname);
                        break;

                    case "MobilePhone":
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.MobilePhone)
                                   : data.OrderBy(g => g.MobilePhone);
                        break;

                    case "Email":
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.Email)
                                   : data.OrderBy(c => c.Email);
                        break;

                    case "ContactTypeName":
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.ContactType.ContactTypeName)
                                   : data.OrderBy(c => c.ContactType.ContactTypeName);
                        break;

                    case "IsActive":
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.IsActive)
                                   : data.OrderBy(c => c.IsActive);
                        break;
                    default:
                        data = sortDescending
                                   ? data.OrderByDescending(c => c.ContactId)
                                   : data.OrderBy(c => c.ContactId);
                        break;
                }
            }

            return data;
        }

        /// <summary>
        /// Gets the list query.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>Contact list</returns>
        public static IQueryable<Contact> GetListQuery(IQueryable<Contact> data, AContactFilter filter)
        {
            // Filter by first name
            if (filter.FirstName != null)
            {
                data = data.Where(c => c.FirstName.StartsWith(filter.FirstName));
            }

            // Filter by Surname name
            if (filter.Surname != null)
            {
                data = data.Where(c => c.Surname.StartsWith(filter.Surname));
            }

            // Filter by in-active & active contact
            if (!filter.IncludeInactive)
            {
                data = data.Where(c => c.IsActive);
            }

            return data;
        }

        /// <summary>
        /// Gets the list count.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <returns>Number of list count</returns>
        public int GetListCount(AContactFilter filter)
        {
            var data = from c in _dataContext.Contacts
                       select c;

            return GetListQuery(data, filter).Count();
        }
    }
}